﻿#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <mysql/mysql.h>
#include "cJSON.h"
#define LOCAL_IP  "192.168.0.166"
#define LOCAL_PORT 9877


#define REMOTE_IP  "192.168.0.166"
#define REMOTE_PORT 9876
typedef struct pass_card
{
	char type[20];
	char name[20];
	char passcard[20]; 
}P_C;
/*
函数功能：解包至打卡结构体
函数参数：P_C *pass-打卡结构体
函数返回值：char *
*/
char * unPassPack(P_C *pass);
/*
函数功能：服务器查询所以打卡信息并发送至客户端
函数参数：MYSQL mysql-数据库，int client_sock-客户端套接字
函数返回值：void
*/
int ServeChecPassAll(MYSQL mysql,int client_sock);
/*
函数功能：服务器按姓名查询每月打卡并发送至客户端
函数参数：P_C pass-打卡结构体,MYSQL mysql-数据库，int client_sock-客户端套接字
函数返回值：void
*/
int ServeChecPassName(P_C pass,MYSQL mysql,int client_sock);
/*
函数功能：服务器按时间查询每日打卡并发送至客户端
函数参数：P_C pass-打卡结构体,MYSQL mysql-数据库，int client_sock-客户端套接字
函数返回值：void
*/
int ServeChecPassTime(P_C pass,MYSQL mysql,int client_sock);
char p[1024] = {0};
int main(int argc,const char* argv[])
{
	int sc = socket(AF_INET,SOCK_STREAM,0);

	if(sc == -1)
	{
		perror("socket");
		return -1;
	}

	struct sockaddr_in saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(LOCAL_PORT);
	saddr.sin_addr.s_addr = inet_addr(LOCAL_IP);

	int optval = 1;
	//bind 的地址允许重复使用
	//设置sock状态
	setsockopt(sc,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
	int ret = bind(sc,(struct sockaddr*)&saddr,sizeof(saddr));
	if(ret == -1)
	{
		perror("bind");
		return -1;
	}
	//启动监听
	int listen_is = listen(sc,10);
	if(listen_is == -1)
	{
		perror("listen");
		exit(1);
	}
	printf("监听已启动");
	struct sockaddr_in peer_addr;
	int peer_len = sizeof(peer_addr);

	//数据库连接
	MYSQL mysql;
    MYSQL *flag = NULL;
	//数据库初始化
    mysql_init(&mysql);
    flag = mysql_real_connect(&mysql,\
        "localhost","root","12345678",\
        "paccount",0,NULL,0);
    if (flag == NULL)
    {
        printf("mysql connect is error:%s",mysql_error(&mysql));
        exit(1);
    }else
    {
        printf("mysql connect is success\n");
    }
	//数据库信息读取存入temp
	char temp[1024] = {0};
	P_C pass;

	//接受数据包
	memset(&pass,0,sizeof(P_C));
	memset(&peer_addr,0,sizeof(peer_addr));
	//连接并接收数据包
	int client_sock = accept(sc,(struct sockaddr*)&peer_addr,&peer_len);
	printf("连接已经建立\n");
	printf("ip:%s,port:%d\n",inet_ntoa(peer_addr.sin_addr),\
		ntohs(peer_addr.sin_port));
	while(1)
	{
		memset(p,0,sizeof(p));
		//读取数据至p字符串
		int re = read(client_sock,p,1024);
		//解包
		unPassPack(&pass);
		//打卡
		if (strcmp(pass.type,"passcard") == 0)
		{
			sprintf(temp,"insert into pass20241204(name,passcard)\
				values('%s','%s')",pass.name,pass.passcard);
			if(mysql_query(&mysql,temp) == 1)
			{
				printf("%s\n",mysql_error(&mysql));
				exit(1);
			}
		}
		//查询所以打卡信息
		if (strcmp(pass.type,"checkpassall") == 0)
		{
			ServeChecPassAll(mysql,client_sock);
		}
		//按姓名查询每月打卡
		if (strcmp(pass.type,"checkpassname") == 0)
		{
			ServeChecPassName(pass,mysql,client_sock);
		}
		//按时间查询每日打卡
		if (strcmp(pass.type,"checkpasstime") == 0)
		{
			ServeChecPassTime(pass,mysql,client_sock);
		}
	}
	close(sc);
    return 0;
}
//解包
char * unPassPack(P_C *pass)
{
	//将p中的字符串转为json对象
	cJSON* root = cJSON_Parse(p);
	//按照键获取json对象的值
	cJSON* type = cJSON_GetObjectItem(root,"type");
	cJSON* name = cJSON_GetObjectItem(root,"name");
	cJSON* passcard = cJSON_GetObjectItem(root,"passcard");
	//将json对象的值获取对应类型的值
	strcpy(pass->type,cJSON_GetStringValue(type));
	strcpy(pass->name,cJSON_GetStringValue(name));
	strcpy(pass->passcard,cJSON_GetStringValue(passcard));
	//释放json对象
	cJSON_Delete(root);
}
//查询所以打卡信息
int ServeChecPassAll(MYSQL mysql,int client_sock)
{
	char temp[1024] = {0};
	MYSQL_RES *res = NULL;
    MYSQL_ROW row;
	sprintf(temp,"select * from pass20241204");
	if(mysql_query(&mysql,temp) == 1)
	{
		printf("%s\n",mysql_error(&mysql));
		exit(1);
	}
	//获得结果集
	res = mysql_store_result(&mysql);
	if (res == NULL)
	{
		printf("查无信息\n");
	}
	//显示所有数据
	for (int j = 0; j < mysql_num_rows(res); j++)
	{
		row = mysql_fetch_row(res);
		memset(p,0,sizeof(p));
		for (int i = 0; i < mysql_num_fields(res); i++)
		{
			if(row[i]!=NULL)
			{
				strcat(p,row[i]);
				strcat(p,"\t");
			}
		}
		strcat(p,"\n");
		//发送数据给客户端
		write(client_sock,p,strlen(p));
		//等待客户端回应信息isok
		while(1)
		{
			memset(p,0,sizeof(p));
			read(client_sock,p,1024);
			if (strcmp(p,"isok")==0)
			{
				break;
			}
		}
	}
	//发送结束信息quit给客户端
	if (mysql_num_rows(res) == 0)
	{
		write(client_sock,"nothing",7);
	}else
	{
		write(client_sock,"quit",4);
	}
}
//按姓名查询每月打卡
int ServeChecPassName(P_C pass,MYSQL mysql,int client_sock)
{
	char temp[1024] = {0};
	MYSQL_RES *res = NULL;
    MYSQL_ROW row;
	sprintf(temp,"select name,passcard from pass20241204 where name = '%s'\
					",pass.name);
	if(mysql_query(&mysql,temp) == 1)
	{
		printf("%s\n",mysql_error(&mysql));
		exit(1);
	}
	//获得结果集
	res = mysql_store_result(&mysql);
	//显示所有数据
	for (int j = 0; j < mysql_num_rows(res); j++)
	{
		row = mysql_fetch_row(res);
		memset(p,0,sizeof(p));
		for (int i = 0; i < mysql_num_fields(res); i++)
		{
			if(row[i]!=NULL)
			{
				strcat(p,row[i]);
				strcat(p,"\t");
			}
		}
		strcat(p,"\n");
		//发送数据给客户端
		write(client_sock,p,strlen(p));
		//等待客户端回应信息isok
		while(1)
		{
			memset(p,0,sizeof(p));
			read(client_sock,p,1024);
			if (strcmp(p,"isok")==0)
			{
				break;
			}
		}
	}
	//发送结束信息quit给客户端
	if (mysql_num_rows(res) == 0)
	{
		write(client_sock,"nothing",7);
	}else
	{
		write(client_sock,"quit",4);
	}
}
//按时间查询每日打卡
int ServeChecPassTime(P_C pass,MYSQL mysql,int client_sock)
{
	char temp[1024] = {0};
	MYSQL_RES *res = NULL;
    MYSQL_ROW row;
	sprintf(temp,"select name,passcard from pass20241204 where \
		passcard >= '%s 00:00:00' and passcard <= \
		'%s 23:59:59'",pass.passcard,pass.passcard);
	if(mysql_query(&mysql,temp) == 1)
	{
		printf("%s\n",mysql_error(&mysql));
		exit(1);
	}
	//获得结果集
	res = mysql_store_result(&mysql);
	//显示所有数据
	for (int j = 0; j < mysql_num_rows(res); j++)
	{
		row = mysql_fetch_row(res);
		memset(p,0,sizeof(p));
		for (int i = 0; i < mysql_num_fields(res); i++)
		{
			if(row[i]!=NULL)
			{
				strcat(p,row[i]);
				strcat(p,"\t");
			}
		}
		strcat(p,"\n");
		//发送数据给客户端
		write(client_sock,p,strlen(p));
		//等待客户端回应信息isok
		while(1)
		{
			memset(p,0,sizeof(p));
			read(client_sock,p,1024);
			if (strcmp(p,"isok")==0)
			{
				break;
			}
		}
	}
	//发送结束信息quit给客户端
	if (mysql_num_rows(res) == 0)
	{
		write(client_sock,"nothing",7);
	}else
	{
		write(client_sock,"quit",4);
	}
}